#include "MainHeader.h"
sChecks chkRes[8];
//May need two procs, i'm hoping for just one.
BOOL CALLBACK  SEProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){


	
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message) 
	{
	case WM_INITDIALOG:
		StatEditor.me = hWnd;
		StatEditor.InitDialog();
		break;
		
		
	case WM_LBUTTONDOWN:
		
		
		break;
	case WM_COMMAND:
		switch(LOWORD(wParam)){
			 case lstNumbers:
				if(HIWORD(wParam)==LBN_SELCHANGE)
				{
				
					StatEditor.SpritePreview.id = StatEditor.SpriteList.GetListIndex();
					StatEditor.LoadSprite();
					StatEditor.SetupPreview();

				}
			break;
			case cmdSavestats:
               StatEditor.SaveSprite();
            break;
			case WM_DESTROY:
				ShowWindow(hWnd,SW_HIDE);
				break;	
	
		}
		break;
	case WM_VSCROLL:	// exact same idea, but V scroll instead of H scroll
		
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		
	
	
	
       StatEditor.SpritePreview.PreviewSprite.TransBlit
		   (hdc,425,42,
	    	(StatEditor.SpritePreview.Borders.right -StatEditor.SpritePreview.Borders.left),	
	        (StatEditor.SpritePreview.Borders.bottom-StatEditor.SpritePreview.Borders.top),
			0,
			0);
	   	EndPaint(hWnd, &ps);
		break;
		case WM_SHOWWINDOW:
		 // LoadCurSprite();	
			break;
			
			
	}
	
//return DefWindowProc(hWnd, message, wParam, lParam);
	return 0;
}
int cStatEd::InitDialog(){
    int i = 0;
	char buff[256];
	SpriteList.Init(GetDlgItem(me,lstNumbers));
	SpriteList.Clear();
    for(i = 0x0;i<0x100;i++){
      sprintf(buff,"%X",i);
	  SpriteList.Additem(buff);
	}
    Health=GetDlgItem(me,txtHealth);
	Damage=GetDlgItem(me,txtDMG);
	chkRes[0].SetCnt(GetDlgItem(me,chkBit1));
	chkRes[1].SetCnt(GetDlgItem(me,chkBit2));
	chkRes[2].SetCnt(GetDlgItem(me,chkBit4));
	chkRes[3].SetCnt(GetDlgItem(me,chkBit8));
    chkRes[4].SetCnt(GetDlgItem(me,chkBit10));
	chkRes[5].SetCnt(GetDlgItem(me,chkBit20));
	chkRes[6].SetCnt(GetDlgItem(me,chkBit40));
	chkRes[7].SetCnt(GetDlgItem(me,chkBit80));
	//ZM stuff
	shp=GetDlgItem(me,txtshp);
	lhp=GetDlgItem(me,txtlhp);
	m=GetDlgItem(me,txtm);
	sm=GetDlgItem(me,txtsm);
	pb=GetDlgItem(me,txtpb);
	//MF
    u1=GetDlgItem(me,txtu1);
	u2=GetDlgItem(me,txtu2);
	u3=GetDlgItem(me,txtu3);
	ud=GetDlgItem(me,txtud);
	return 0;
}
int cStatEd::Switch(){
	if(GameEngine->isZM()) SetUpForZM();//change restance and disables MF editing
	if(GameEngine->isMF()) SetUpForMF();
	return 0;
}
cStatEd::cStatEd(){
}
cStatEd::~cStatEd(){
}
int cStatEd::SetUpForMF(){
   
    
   
	//ZM stuff
	EnableWindow(	shp,0);
	EnableWindow(lhp,0);
	EnableWindow(m,0);
    EnableWindow(sm,0);
    EnableWindow(pb,0);
    EnableWindow(u1,1);
	EnableWindow(u2,1);
	EnableWindow(u3,1);
    EnableWindow(ud,1);
	//MF
    
    memset(&ZMSprite,0,sizeof(ZMSprite));

	
	return 0;
}
int cStatEd::SetUpForZM(){
   
    
   
	//ZM stuff
	EnableWindow(	shp,1);
	EnableWindow(lhp,1);
	EnableWindow(m,1);
    EnableWindow(sm,1);
    EnableWindow(pb,1);
    EnableWindow(u1,0);
	EnableWindow(u2,0);
	EnableWindow(u3,0);
    EnableWindow(ud,0);
	//MF
   
	
	return 0;
}
int cStatEd::LoadSprite(){
	char buffer[256]={0};
    u8 res=0;

	if(GameEngine->isZM() ==0) {
    //2b0d68 + (enID * 18)
    fseek(GBA.ROM,0x2b0d68 + ((SpritePreview.id)* 18),SEEK_SET);
    fread(&ZMSprite,sizeof(ZMSprite),1,GBA.ROM);
	sprintf(buffer,"%d",ZMSprite.health);
    SetWindowText(Health,buffer);
	sprintf(buffer,"%d",ZMSprite.Dmg);
    SetWindowText(Damage,buffer);
	res=ZMSprite.resistance;
	sprintf(buffer,"%d",ZMSprite.smallHP);
	SetWindowText(shp,buffer);
	sprintf(buffer,"%d",ZMSprite.largehp);
	SetWindowText(lhp,buffer);
    sprintf(buffer,"%d",ZMSprite.missiles);
	SetWindowText(m,buffer);
    sprintf(buffer,"%d",ZMSprite.supermissiles);
	SetWindowText(sm,buffer);
    sprintf(buffer,"%d",ZMSprite.PowerBombs);
	SetWindowText(pb,buffer);


	//Load Items

	}else if(GameEngine->isMF()){
    fseek(GBA.ROM,0x2E4D4C  + ((SpritePreview.id)* 14),SEEK_SET);
	fread(&FusionSprite,sizeof(FusionSprite),1,GBA.ROM);
	// fseek(GBA.ROM,0x2b0d68 + ((SpritePreview.id)* 18),SEEK_SET);
    //fread(&FusionSprite,sizeof(FusionSprite),1,GBA.ROM);
	sprintf(buffer,"%d",FusionSprite.Health);
    SetWindowText(Health,buffer);
	sprintf(buffer,"%d",FusionSprite.Damage);
    SetWindowText(Damage,buffer);
    res=FusionSprite.resistance;
	sprintf(buffer,"%X",FusionSprite.unknown1);
	SetWindowText(u1,buffer);
	sprintf(buffer,"%X",FusionSprite.unknown2);
	SetWindowText(u2,buffer);
    sprintf(buffer,"%X",FusionSprite.unknown3);
    SetWindowText(u3,buffer);
	sprintf(buffer,"%X",FusionSprite.unknownDamage);
	SetWindowText(ud,buffer);
	}
	chkRes[0].value(res & 0x1  ? 1:0);
    chkRes[1].value(res & 0x2  ? 1:0);
	chkRes[2].value(res & 0x4  ? 1:0);
    chkRes[3].value(res & 0x8  ? 1:0);
	chkRes[4].value(res & 0x10 ? 1:0);
    chkRes[5].value(res & 0x20 ? 1:0);
	chkRes[6].value(res & 0x40 ? 1:0);
    chkRes[7].value(res & 0x80 ? 1:0);
	return 0;
}
int cStatEd::SaveSprite(){
	char buffer[256]={0};
	u16 blah=0;
	u8 res=0;
	res|=	(chkRes[0].value() ? 1:0);
	res|=   (chkRes[1].value() ? 2:0);
	res|=   (chkRes[2].value() ? 4:0);
 	res|=   (chkRes[3].value() ? 8:0);
	res|=   (chkRes[4].value() ? 0x10:0);
	res|=   (chkRes[5].value() ? 0x20:0);
	res|=   (chkRes[6].value() ? 0x40:0);
	res|=   (chkRes[7].value() ? 0x80:0);
	if(GameEngine->isZM() ==0) {
    //2b0d68 + (enID * 18)
   
		
		GetWindowText(Health,buffer,256);
		sscanf(buffer,"%d",&ZMSprite.health);
		GetWindowText(Damage,buffer,256);
		sscanf(buffer,"%d",&ZMSprite.Dmg);
		ZMSprite.resistance = res;
		 
		GetWindowText(shp,buffer,256);
		sprintf(buffer,"%d",&ZMSprite.smallHP);
		GetWindowText(lhp,buffer,256);
		sscanf(buffer,"%d",&ZMSprite.largehp);
		GetWindowText(m,buffer,256);
		sscanf(buffer,"%d",&ZMSprite.missiles);
		GetWindowText(sm,buffer,256);
		sscanf(buffer,"%d",&ZMSprite.supermissiles);

		GetWindowText(pb,buffer,256); 
		sscanf(buffer,"%d",&ZMSprite.PowerBombs);
		
		fseek(GBA.ROM,0x2b0d68 + ((SpritePreview.id)* 18),SEEK_SET);
		fwrite(&ZMSprite,1,18,GBA.ROM);
		fclose(GBA.ROM);
		GBA.ROM=fopen(GBA.FileLoc,"r+b");
		LoadSprite();
		//Load Items

	}else if(GameEngine->isMF()){
		GetWindowText(Health,buffer,256);
		sscanf(buffer,"%d",&FusionSprite.Health);
		GetWindowText(Damage,buffer,256);
		sscanf(buffer,"%d",&FusionSprite.Damage);
		FusionSprite.resistance = (res);
		GetWindowText(u1,buffer,256);
		sscanf(buffer,"%X",&FusionSprite.unknown1);
		GetWindowText(u2,buffer,256);
		sscanf(buffer,"%X",&FusionSprite.unknown2);
		GetWindowText(u3,buffer,256);
		sscanf(buffer,"%X",&FusionSprite.unknown3);
		GetWindowText(ud,buffer,256); 
	    sscanf(buffer,"%X",&FusionSprite.unknownDamage);
		fseek(GBA.ROM,0x2E4D4C + ((SpritePreview.id)* 14),SEEK_SET);
	//	fwrite(&FusionSprite,1,14,GBA.ROM);
        
		
		fwrite(&FusionSprite.Health,2,1,GBA.ROM);
		fwrite(&FusionSprite.Damage,2,1,GBA.ROM);
	    fwrite(&FusionSprite.unknownDamage,2,1,GBA.ROM);
		fwrite(&res,1,1,GBA.ROM);
	    fwrite(&FusionSprite.unknown6,1,1,GBA.ROM);
		fwrite(&FusionSprite.unknown1,2,1,GBA.ROM);
		fwrite(&FusionSprite.unknown2,2,1,GBA.ROM);
		fwrite(&FusionSprite.unknown3,2,1,GBA.ROM);
	   // fwrite(&FusionSprite.end,2,1,GBA.ROM);
	   
		GBA.Reopen();

	}

	return 0;
}
int cStatEd::SetupPreview(){
long GFXPnt=0;
long PalPnt=0;
long palsize=0;
long addybuf=0;
long size=0;
int i=0;
int ii=0;
u8 decompbuf[32687]= {0};
SpritePreview.PreviewSprite.Clear();
InvalidateRect(me,0,1);
if(SpriteOAM[SpritePreview.id]==0) return 0;
	memset(&SpritePreview.PreRAM[0x4000], 0, 0x4000);
CompHeader thiscompheader;

	u16 transferpal[256]={0};

	int  X=0;
	long off=0;
	int x =0;
	memset(SprPal,0,sizeof(SprPal));
//	memset(&GBASprPal[128],0,sizeof(GBASprPal)-128);
//    memset(&SprPal,0,sizeof(SprPal));
	if(GameEngine->isZM()){
		GFXPnt= sprgfxpnt + (SpritePreview.id-0x10) * 4;
		
		fseek(GBA.ROM, sprgfxpnt + (SpritePreview.id -0x10 ) * 4, SEEK_SET);
		fread(&off, 4, 1, GBA.ROM);
		fseek(GBA.ROM, off-0x8000000, SEEK_SET);
		fread(&thiscompheader.check_ten, 1, 1, GBA.ROM);       //Check byte should be 0x10 for lz
		fread(&thiscompheader.l3, 1, 1, GBA.ROM);
		fread(&thiscompheader.l2, 1, 1, GBA.ROM);
		fread(&thiscompheader.l1, 1, 1, GBA.ROM);

		PalPnt = sprpalpnt + (SpritePreview.id-0x10) * 4;
	
		palsize= (thiscompheader.l2 & 0xF8) * 2;

	
	}else if(GameEngine->isMF()){
        GFXPnt= 0x79A5D8 + (SpritePreview.id-0x10) * 4;
		


		PalPnt= 0x79A8D4 + (SpritePreview.id-0x10) * 4;

		palsize=  ((MFSprSize[(SpritePreview.id-0x10)<<1]/2048)*16);


	}
	
    
       
		fseek(GBA.ROM, PalPnt , SEEK_SET);
		fread(&addybuf, 4, 1, GBA.ROM);
		fseek(GBA.ROM, addybuf-0x8000000, SEEK_SET);
		fread(&transferpal, 1, (paltransfer[x].Size)*2, GBA.ROM);
         
//	if(paltransfer[x][1] == 0) continue;
	 memcpy(&GBASprPal[128], &transferpal, (paltransfer[x].Size)*2);
           
	 GBA.DecodePal(GBASprPal, SpritePreview.PreviewPal, 16, 0);
  


	
		switch(GameEngine->isZM()){
				case 0:
					fseek(GBA.ROM, GFXPnt, SEEK_SET);
					fread(&addybuf, 4, 1, GBA.ROM);
					fseek(GBA.ROM, addybuf-0x8000000, SEEK_SET);
					fread(GBA.CompBuffer, 1, sizeof(GBA.CompBuffer), GBA.ROM);
					size = GBA.LZ77UnComp(GBA.CompBuffer, decompbuf);
					memcpy(&SpritePreview.PreRAM[0x4000], &decompbuf, size);
				break; 
				case 1:
                    size = MFSprSize[(SpritePreview.id-0x10)<<1];
					fseek(GBA.ROM, GFXPnt, SEEK_SET);
					fread(&addybuf, 4, 1, GBA.ROM);
					fseek(GBA.ROM, addybuf-0x8000000, SEEK_SET);
				    fread(&SpritePreview.PreRAM[0x4000], 1, size, GBA.ROM);
				break;
		}
	

	SpritePreview.Tiles.Load(SpritePreview.PreRAM, 1023);
    DecodeSprite(& SpritePreview,SpriteOAM[SpritePreview.id]);
	DrawPSprite(& SpritePreview);
	InvalidateRect(me,0,1);
	return 0;
}


int DecodeSprite(SprGBuf* tSprite,u32 Offset) {
	
	u16 spritecount=0;

	u16 i=0;
	u32 so=0; 
	//Dim bam As String
	u16 OAM0=0;
	u16 OAM1=0;
	u16 OAM2=0;

		if(!Offset) 
		return 0;
		
		//Get #1, pointer2offset(SpriteOAM(ttype)) + 1, bam2
		//Seek #1, pointer2offset(SpriteOAM(ttype)) + 1 //0x2E0F88 + 1 //0x2C480E + 1
	
		fseek(GBA.ROM,  Offset, SEEK_SET);
			if(OAMED==false){
    			fread(&so, 4, 1, GBA.ROM);
				fseek(GBA.ROM, so-0x8000000, SEEK_SET);
			}
		fread(&tSprite->maxparts, 2, 1, GBA.ROM);
		
		
		for( i=0; i< tSprite->maxparts; i++) {
			fread(&tSprite->OAM[i].enOAM.OAM0, 2, 1, GBA.ROM);
			fread(&tSprite->OAM[i].enOAM.OAM1, 2, 1, GBA.ROM);
			fread(&tSprite->OAM[i].enOAM.OAM2, 2, 1, GBA.ROM);
		}
	

		
		for( i=0; i<  tSprite->maxparts; i++) {
			OAM0=tSprite->OAM[i].enOAM.OAM0;
			OAM1=tSprite->OAM[i].enOAM.OAM1;
			OAM2=tSprite->OAM[i].enOAM.OAM2;
			tSprite->OAM[i].deOAM.yCoord = (OAM0 & 0xFF);
			
			tSprite->OAM[i].deOAM.objRot = GetBitField(OAM0, 8, 1);
			tSprite->OAM[i].deOAM.DSaOD = GetBitField(OAM0, 9, 1);
			tSprite->OAM[i].deOAM.ObjMode = GetBitField(OAM0, 10, 2);
			tSprite->OAM[i].deOAM.ObjMosiac = GetBitField(OAM0, 12, 1);
			tSprite->OAM[i].deOAM.Paltype = GetBitField(OAM0, 13, 1);
			tSprite->OAM[i].deOAM.ObjShape = GetBitField(OAM0, 14, 2);
			
			//OAM1
			tSprite->OAM[i].deOAM.xCoord = GetBitField(OAM1, 0, 8);
			
			if (GetBitField(OAM0, 8, 1) == 1) {
				tSprite->OAM[i].deOAM.rotation = GetBitField(OAM1, 9, 5);
			} else {
				tSprite->OAM[i].deOAM.HorizontalFlip = (OAM1 & 0x400 ? 1:0);
				tSprite->OAM[i].deOAM.VerticalFlip = (OAM1 & 0x800	? 1:0);
			}
			
			tSprite->OAM[i].deOAM.ObjSize =OAM1>>14;
			tSprite->OAM[i].deOAM.TileNumber = OAM2 & 0x3FF;
			tSprite->OAM[i].deOAM.Palette = (OAM2 & 0xF000) / 0x1000;
		
	}
	return 0;
}





int DrawPSprite( SprGBuf* SpriteDetails) {
	int width=0;
	int height=0;
	int i =0;
	int Tile=0;
	int bTile=0;
	int Pal=0;
	int fw=0;
	int fh=0;
	int ty=0;
	int tx=0;
	int sx=0;
	int sy=0;
	int xFlip=0;
	int yFlip=0;
	RECT PartSize[128];
	const u8 objSizes[3][4][2]=
	{
		{ { 8, 8}, {16,16}, {32,32}, {64,64} }, 
		{ {16, 8}, {32, 8}, {32,16}, {64,32} },
		{ { 8,16}, { 8,32}, {16,32}, {32,64} },
	};
	
	Image OamBuffer; 
	


	sx = 0;
	sy = 0;

	tx = 0;
	ty = 0;
    OamBuffer.Create(256, 256);
	OamBuffer.SetPalette(SpriteDetails->PreviewPal);



	//Draw reverse order
	// for(size = SpriteNo[cursprite]; size>0; size--) {
	
	for(i = 0; i<SpriteDetails->maxparts; i++) {
	    

		if ( SpriteDetails->OAM[i].deOAM.ObjShape == 3)
			continue;

		sx = ( SpriteDetails->OAM[i].enOAM.OAM1 & 511);
		sy = ( SpriteDetails->OAM[i].enOAM.OAM0 & 255);
		if (sy & 0x80) 
			sy = sy - 256; //check for the negative
		if (sx &  0x100)  
			sx = sx - 511; //same here
         
		sx = sx + 128;
		sy = sy + 128;
		//Set up the basic tile
    
       
	
		int Pal = (( SpriteDetails->OAM[i].enOAM.OAM2&0xF000));

		//MsgBox "Out of Memory Bounds": Exit Function
		Tile=Pal  + 	( SpriteDetails->OAM[i].enOAM.OAM2 & 0x3FF);
		//Tile+= SpriteDetails->OAM[i];deOAM.VerticalFlip*0x800;

		//Now switch on this and find the sprite width and height.


		width = objSizes[ SpriteDetails->OAM[i].enOAM.OAM0>>14][ SpriteDetails->OAM[i].enOAM.OAM1>>14][0];
		height= objSizes[ SpriteDetails->OAM[i].enOAM.OAM0>>14][ SpriteDetails->OAM[i].enOAM.OAM1>>14][1];
        PartSize[i].left =sx;
		PartSize[i].top =sy;
        PartSize[i].right =width;
		PartSize[i].bottom =height;
		xFlip= yFlip= fh= fw= 0;

		if( SpriteDetails->OAM[i].enOAM.OAM1 & 0x1000) {
			//formula goes here;
			xFlip= width/8-1; //if width = 16 y
			fw = 0x400;
		} 
		if( SpriteDetails->OAM[i].enOAM.OAM1 & 0x2000 ) {
			yFlip = height/8-1;
			fh = 0x800;
		} 

		for(ty=0; ty<height/8; ty++) {

			for(tx=0; tx<width/8; tx++) {

				OamBuffer.Draw(SpriteDetails->Tiles, sx + (tx^xFlip)*8,
					sy + ((ty)^yFlip)*8, Tile+tx+(ty*32)+fh+fw);
				
			}
		}
		

/*     
		HDC hdc= OamBuffer.DC();
		HPEN pen;
		pen= CreatePen(PS_SOLID, 1, i==0 ? RGB(255,0,0) : RGB(0, 255, 255));

		HPEN oldPen= (HPEN)SelectObject(hdc, pen);
		HBRUSH oldBrush= (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH));
		Rectangle(hdc, sx, sy, sx+width, sy+width);
		SelectObject(hdc, oldBrush);		
		SelectObject(hdc, oldPen);*/
	}

	//Determine i
	SpriteDetails->Borders.left =PartSize[0].left;
	SpriteDetails->Borders.top =PartSize[0].top;
    SpriteDetails->Borders.right =PartSize[0].left+PartSize[0].right;
	SpriteDetails->Borders.bottom =PartSize[0].top+PartSize[0].bottom;

	for(i = 1; i<SpriteDetails->maxparts; i++) {
		 //Check for top coord 
		 //0 = Starting X
		 //1 = Startiny Y
		 //2 = Width
		 //3 = Height
		if(PartSize[i].left<SpriteDetails->Borders.left) 
			SpriteDetails->Borders.left = PartSize[i].left;
		if(PartSize[i].top<SpriteDetails->Borders.top) 
			SpriteDetails->Borders.top = PartSize[i].top;

		SpriteDetails->Borders.right= 
			max(SpriteDetails->Borders.right, PartSize[i].left+PartSize[i].right);
		SpriteDetails->Borders.bottom= 
			max(SpriteDetails->Borders.bottom, PartSize[i].top+PartSize[i].bottom);

	}
	
	SpriteDetails->PreviewSprite.Create(SpriteDetails->Borders.right-SpriteDetails->Borders.left,	
		SpriteDetails->Borders.bottom-SpriteDetails->Borders.top);

	SpriteDetails->PreviewSprite.SetPalette(	SpriteDetails->PreviewPal);
/*	BitBlt(SpritePics[cursprite].DC(), 0, 0, 
		OverallSize[cursprite].right-OverallSize[cursprite].left,
		OverallSize[cursprite].bottom-OverallSize[cursprite].top,
		OamBuffer.DC(), OverallSize[cursprite].left, OverallSize[cursprite].top, 
		SRCCOPY);*/
	OamBuffer.Blit(SpriteDetails->PreviewSprite.DC(), 0, 0, 
		SpriteDetails->Borders.right-SpriteDetails->Borders.left,	
		SpriteDetails->Borders.bottom-SpriteDetails->Borders.top,SpriteDetails->Borders.left,SpriteDetails->Borders.top);

	


	return 0;
}



